﻿namespace LMT.Securities
{
    using System;
    using System.Text;
    using System.Security.Cryptography;

    /// <summary>
    /// 
    /// </summary>
    public sealed class Encryption
    {
        /// <summary>
        /// Encrypts the specified to encrypt.
        /// </summary>
        /// <param name="toEncrypt">To encrypt.</param>
        /// <param name="securityKey">The security key.</param>
        /// <param name="useHashing">if set to <c>true</c> [use hashing].</param>
        /// <returns></returns>
        public static byte[] Encrypt(byte[] toEncrypt, string securityKey, bool useHashing)
        {
            byte[] keyArray;

            //If hashing use get hashcode regards to your key
            if (useHashing)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(securityKey));
                //Always release the resources and flush data
                // of the Cryptographic service provide. Best Practice
                hashmd5.Clear();
            }
            else
            {
                keyArray = UTF8Encoding.UTF8.GetBytes(securityKey);
            }

            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            //set the secret key for the tripleDES algorithm
            tdes.Key = keyArray;
            //mode of operation. there are other 4 modes.
            //We choose ECB(Electronic code Book)
            tdes.Mode = CipherMode.ECB;
            //padding mode(if any extra byte added)

            tdes.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = tdes.CreateEncryptor();
            //transform the specified region of bytes array to resultArray
            byte[] resultArray = cTransform.TransformFinalBlock(toEncrypt, 0, toEncrypt.Length);
            //Release resources held by TripleDes Encryptor
            tdes.Clear();

            //Return the encrypted data into unreadable string format
            return resultArray;
        }

        /// <summary>
        /// Decrypts the specified cipher string.
        /// </summary>
        /// <param name="encryptedByte">The encrypted byte.</param>
        /// <param name="securityKey">The security key.</param>
        /// <param name="useHashing">if set to <c>true</c> [use hashing].</param>
        /// <param name="decryptedByte">The decrypted byte.</param>
        /// <returns></returns>
        public static bool Decrypt(byte[] encryptedByte, string securityKey, bool useHashing, out byte[] decryptedByte)
        {
            byte[] keyArray;
            decryptedByte = null;

            if (useHashing)
            {
                //if hashing was used get the hash code with regards to your key
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(securityKey));
                //release any resource held by the MD5CryptoServiceProvider

                hashmd5.Clear();
            }
            else
            {
                //if hashing was not implemented get the byte code of the key
                keyArray = UTF8Encoding.UTF8.GetBytes(securityKey);
            }

            TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
            //set the secret key for the tripleDES algorithm
            tdes.Key = keyArray;
            //mode of operation. there are other 4 modes. 
            //We choose ECB(Electronic code Book)

            tdes.Mode = CipherMode.ECB;
            //padding mode(if any extra byte added)
            tdes.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = tdes.CreateDecryptor();

            try
            {
                decryptedByte = cTransform.TransformFinalBlock(encryptedByte, 0, encryptedByte.Length);
            }
            catch
            {
                return false;
            }
            
            //Release resources held by TripleDes Encryptor                
            tdes.Clear();

            return true;
        }
    }
}